重新组织代码
一、抽取不相关的子问题
建议:积极发现并抽取出不相关的子逻辑
- 看看某个函数或代码块,问问自己,这段代码高层次目标是什么?
- 对每一行代码,问问自己,它是直接为了目标而工作吗?这段代码的高层次目标是什么?
- 如果有足够的行数在解决不相关的子问题,抽取代码到独立的函数中
- 例子,计算地球上两个点的最近距离// Return which element of 'array' is closest to the given latitude/longitude.// Models the Earth as a perfect sphere.var findClosestLocation = function(lat, lng, array) {var closest;var closest_dist = Number.MAX_VALUE;for (var i = 0; i < array.length; i += 1) {// Convert both points to radians.var lat_rad = radians(lat);var lng_rad = radians(lng);var lat2_rad = radians(array[i].latitude);var lng2_rad = radians(array[i].longitude);// Use the "Spherical Law of Cosines" formula.var dist = Math.acos(Math.sin(lat_rad) * Math.sin(lat2_rad) +Math.cos(lat_rad) * Math.cos(lat2_rad) *Math.cos(lng2_rad - lng_rad));if (dist < closest_dist) {closest = array[i];closest_dist = dist;}}return closest;};
循环中大部分代码都在解决一个和高层问题无关的子问题:“计算两个坐标之间的球面距离”,所以我们将它抽离出来:
然后函数就变成了,可读性更高,还能做单独测试:
值得明白的一点是,例子中并不是在讲怎么架构,不是从如何解耦出发的,而是从如何抽取不相关的问题出发的。虽然殊途同归,但是思路是不一样的。
意料之外的好处:当抽取不相关子问题成为独立的代码之后,改进这些独立的代码变得更加容易。
过犹不及:过多的抽离子问题,会让整个代码引入过多的小函数,阅读者就需要在不同的函数之间反复跳跃,降低可读性。
二、一次只做一件事
建议:
- 列出代码所做的所有任务
- 尽量把任务拆分到不同的函数中,或者至少是代码中不同的段落中
三、把想法变代码
建议:
- 像对着一个同事一样用自然语言描述代码要做什么
- 注意描述中所用的关键词和短语
- 写出与描述所匹配的代码
清楚描述逻辑
在写代码之前,先清晰的描述(写)出你的逻辑,再进行coding,这样有助于你写出更好的代码。
这不就是传说中的“小黄鸭debug术”吗!
下面这个例子就说明了如何用清晰的逻辑重构代码:
可以将上述逻辑表述为:
于是,代码可以重构为:
三、少写代码
最好读的代码就是:没有代码
质疑和拆分需求
并不是所有程序都要运行得快,100%准确,并且能处理所有的输入。可以根据实际需要,拆分并且削减一部分需求。
保持小的代码库
建议:
- 代码复用,创建更多可复用的“工具”代码
- 减少无用的代码或没有用的功能
- 让代码保持分开的子项目状态
熟悉你周边的库
建议:每个一段时间,花15分钟来阅读标准库中的所有函数/模块/类型的名字,用以了解有什么可以用,下次写新的代码时就会想到。